home *** CD-ROM | disk | FTP | other *** search
/ Aminet 24 / Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso / Aminet / comm / mail / Mutt089src.lha / Mutt-0.89i-AMIGA / src / system.c < prev    next >
C/C++ Source or Header  |  1998-01-28  |  3KB  |  121 lines

  1. /*
  2.  * Copyright (C) 1996-8 Michael R. Elkins <me@cs.hmc.edu>
  3.  * 
  4.  *     This program is free software; you can redistribute it and/or modify
  5.  *     it under the terms of the GNU General Public License as published by
  6.  *     the Free Software Foundation; either version 2 of the License, or
  7.  *     (at your option) any later version.
  8.  * 
  9.  *     This program is distributed in the hope that it will be useful,
  10.  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  *     GNU General Public License for more details.
  13.  * 
  14.  *     You should have received a copy of the GNU General Public License
  15.  *     along with this program; if not, write to the Free Software
  16.  *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  */ 
  18.  
  19. #include "mutt.h"
  20.  
  21. #include <stdlib.h>
  22. #include <signal.h>
  23. #include <string.h>
  24. #include <sys/wait.h>
  25. #include <unistd.h>
  26.  
  27. int _mutt_system (const char *cmd, int flags)
  28. {
  29.  
  30.   int rc = -1;
  31.   struct sigaction act;
  32.   struct sigaction oldcont;
  33.   struct sigaction oldtstp;
  34.   struct sigaction oldint;
  35.   struct sigaction oldquit;
  36.   struct sigaction oldchld;
  37.   sigset_t set;
  38.   pid_t thepid;
  39.  
  40.   /* must block SIGCHLD and ignore SIGINT and SIGQUIT */
  41.  
  42.   act.sa_handler = SIG_IGN;
  43.   act.sa_flags = 0;
  44.   sigemptyset (&(act.sa_mask));
  45.   sigaction (SIGINT, &act, &oldint);
  46.   sigaction (SIGQUIT, &act, &oldquit);
  47.   if (flags & M_DETACH_PROCESS)
  48.   {
  49.     act.sa_flags = SA_NOCLDSTOP;
  50.     sigaction (SIGCHLD, &act, &oldchld);
  51.     act.sa_flags = 0;
  52.   }
  53.   else
  54.   {
  55.     sigemptyset (&set);
  56.     sigaddset (&set, SIGCHLD);
  57.     sigprocmask (SIG_BLOCK, &set, NULL);
  58.   }
  59.  
  60.   act.sa_handler = SIG_DFL;
  61.   sigaction (SIGTSTP, &act, &oldtstp);
  62.   sigaction (SIGCONT, &act, &oldcont);
  63.  
  64. #ifdef AMIGA
  65.   if ((thepid = vfork ()) == 0)
  66. #else
  67.   if ((thepid = fork ()) == 0)
  68. #endif
  69.   {
  70.     /* reset signals for the child */
  71.     sigaction (SIGINT, &act, NULL);
  72.     sigaction (SIGQUIT, &act, NULL);
  73.  
  74.     if (flags & M_DETACH_PROCESS)
  75.     {
  76.       setsid ();
  77. #ifdef AMIGA
  78.       switch (vfork ())
  79. #else
  80.       switch (fork ())
  81. #endif
  82.       {
  83.     case 0:
  84.       sigaction (SIGCHLD, &act, NULL);
  85.       break;
  86.  
  87.     case -1:
  88.       _exit (127);
  89.  
  90.     default:
  91.       _exit (0);
  92.       }
  93.     }
  94.     else
  95.       sigprocmask (SIG_UNBLOCK, &set, NULL);
  96.  
  97.     execl (EXECSHELL, "sh", "-c", cmd, NULL);
  98.     _exit (127); /* execl error */
  99.   }
  100.   else if (thepid != -1)
  101.   {
  102.     /* wait for the child process to finish */
  103.     waitpid (thepid, &rc, 0);
  104.   }
  105.  
  106.   /* reset SIGINT, SIGQUIT and SIGCHLD */
  107.   sigaction (SIGINT, &oldint, NULL);
  108.   sigaction (SIGQUIT, &oldquit, NULL);
  109.   if (flags & M_DETACH_PROCESS)
  110.     sigaction (SIGCHLD, &oldchld, NULL);
  111.   else
  112.     sigprocmask (SIG_UNBLOCK, &set, NULL);
  113.  
  114.   sigaction (SIGCONT, &oldcont, NULL);
  115.   sigaction (SIGTSTP, &oldtstp, NULL);
  116.  
  117.   rc = WIFEXITED (rc) ? WEXITSTATUS (rc) : -1;
  118.  
  119.   return (rc);
  120. }
  121.